/*
 * @Description: 类型断言和类型推导
 * @Autor: HuiSir<273250950@qq.com>
 * @Date: 2021-05-06 18:42:43
 * @LastEditTime: 2021-05-20 15:47:25
 */

(function () {

    /**
     * 断言：告诉编译器我是什么，告诉编译器我确定我在干嘛
     */


    /**
     * 类型断言
     * 方式一：在类型变量名之前使用`<string>`尖括号中类型的形式对变量进行断言
     * 方式二：`变量 as 类型`
     * 变量后若存在表达式，需要使用括号括起来`(<类型>变量)`或`(变量 as 类型)`
     */

    // 比如我要拿到一个数据的length,但编译器无法确定我的数据是否有length
    // 这时候可以使用类型断言，断定这个数据是数组或有length属性的其他值
    // 类型断言类似于其他语言中的类型转换，但是只在编译阶段起作用，不影响运行结果

    /**
     * 类型断言-->明确类型
     */
    function getLength(str: number | string): number {
        // return str.toString().length
        // 如果str是string类型，那么没必要调用toString方法
        // 但现在编译器不知道str是不是string

        /*
            if (str.length) {   // 类型“string | number”上不存在属性“length”。类型“number”上不存在属性“length”。
                return str.length
            } else {
                return str.toString().length
            }
        */

        if ((<string>str).length) {
            return (str as string).length
        } else {
            return str.toString().length
        }
    }

    console.log(getLength(12345)) // 5

    /**
     * 类型断言2：使用在变量名之后添加感叹号`！`来进行非空断言（非void、undefined、null）
     */
    interface Entity {
        name: string
    }
    function processEntity(e?: Entity): string {
        return e!.name  // 对象可能为“未定义”
    }

    /**
     * 类型推导：ts是在没有明确指定数据类型时推断出类型
     * 已经赋值的数据再次赋值会根据第一次复制的数据推断的类型进行限制
     */
    let a = "xiaoming"
    // a = 10  // 报错：不能将类型“number”分配给类型“string”

})()
